#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
HTTP客户端异常类

该模块定义了HTTP客户端模块中使用的各种异常类型，提供了统一的异常继承体系，
方便进行分类处理和错误追踪。

创建时间: 2023-07-15
作者: Python Tools Team
"""

from typing import Optional, Dict, Any, Union
from modules.exception.exception_types import BaseAppException
import requests


class HttpClientException(BaseAppException):
    """
    HTTP客户端基础异常类，所有HTTP客户端相关异常的基类
    
    属性:
        message: 异常消息
        code: 异常代码
        details: 异常详细信息
        cause: 原始异常（如果由其他异常引起）
    """
    
    def __init__(self, 
                 message: str = "HTTP客户端异常", 
                 code: str = "E100000", 
                 details: Optional[Dict[str, Any]] = None, 
                 cause: Optional[Exception] = None):
        super().__init__(message=message, code=code, details=details, cause=cause)


class RequestException(HttpClientException):
    """
    请求异常，表示在构建或发送HTTP请求时发生的错误
    
    属性:
        request: 导致异常的请求对象
    """
    
    def __init__(self, 
                 message: str = "HTTP请求异常", 
                 code: str = "E100100", 
                 details: Optional[Dict[str, Any]] = None, 
                 cause: Optional[Exception] = None,
                 request: Optional[requests.Request] = None):
        self.request = request
        if request and not details:
            details = {
                'method': request.method,
                'url': request.url,
                'headers': dict(request.headers) if request.headers else None,
            }
        super().__init__(message=message, code=code, details=details, cause=cause)


class ResponseException(HttpClientException):
    """
    响应异常，表示在处理HTTP响应时发生的错误
    
    属性:
        response: 导致异常的响应对象
        status_code: HTTP状态码
    """
    
    def __init__(self, 
                 message: str = "HTTP响应异常", 
                 code: str = "E100200", 
                 details: Optional[Dict[str, Any]] = None, 
                 cause: Optional[Exception] = None,
                 response: Optional[requests.Response] = None,
                 status_code: Optional[int] = None):
        self.response = response
        self.status_code = status_code or (response.status_code if response else None)
        
        if response and not details:
            details = {
                'status_code': response.status_code,
                'url': response.url,
                'headers': dict(response.headers),
                'content': response.text[:500] + '...' if len(response.text) > 500 else response.text
            }
        super().__init__(message=message, code=code, details=details, cause=cause)


class TimeoutException(HttpClientException):
    """
    超时异常，表示HTTP请求超时
    
    属性:
        timeout: 超时时间（秒）
    """
    
    def __init__(self, 
                 message: str = "HTTP请求超时", 
                 code: str = "E100300", 
                 details: Optional[Dict[str, Any]] = None, 
                 cause: Optional[Exception] = None,
                 timeout: Optional[Union[float, int, tuple]] = None):
        self.timeout = timeout
        if timeout and not details:
            details = {'timeout': timeout}
        super().__init__(message=message, code=code, details=details, cause=cause)